import java.awt.Color;
import java.awt.Graphics;
import java.awt.Panel;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import javax.swing.JButton;
import javax.swing.JRadioButton;
import javax.swing.JSlider;
import javax.swing.JComponent;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;


// Note that the JComponent is set up to listen for mouse clicks
// and mouse movement.  To achieve this, the MouseListener and
// MousMotionListener interfaces are implemented and there is additional
// code in init() to attach those interfaces to the JComponent.


public class SHAFIQSIDEK_Display extends JComponent implements MouseListener, MouseMotionListener
{
	public static final int ROWS = 80;
	public static final int COLS = 100;
       
 	private Speed speed;			//new slower button
        
	//used for population editor
	private Settings settings;		//settings button
	private Done settingsdone;		//boolean for whether settings is active
        
	double mouseX=0;				//mouses x location
	double mouseY=0;				//mouses y location
	int changedx=0;					//cell that is under mouse x
	int changedy=0;					//cell that is under mouse y
	int turn=0;						//generation counter
	private boolean poped=false;	//settings menu
	private final int X_GRID_OFFSET = 25; // 10 pixels from left
	private final int Y_GRID_OFFSET = 40; // 10 pixels from top
	private final int CELL_WIDTH = 5;
	private final int CELL_HEIGHT = 5;
        
	// Note that a final field can be initialized in constructor
	private final int DISPLAY_WIDTH;   
	private final int DISPLAY_HEIGHT;
	private StartButton startStop;//new start button
	private Next next;//new next button
	private Clear clear;//new clear button
	private Reset reset;//new reset button
	
	private boolean[][] life=new boolean[100][80];
	private boolean[][] original=new boolean[100][80];
	private boolean[][] temp=new boolean[100][80];
	private boolean paintloop = false;//whether game is active
	int n=100;//initial speed

	public SHAFIQSIDEK_Display(int width, int height) 
	{
		DISPLAY_WIDTH = width;
		DISPLAY_HEIGHT = height;
		init();
	}


	public void init() 
	{
		setSize(DISPLAY_WIDTH, DISPLAY_HEIGHT);
	
		addMouseListener(this);
		addMouseMotionListener(this);

		//sets locations and initial settings of buttons
		startStop = new StartButton();
		startStop.setBounds(25, 550, 100, 36);
		add(startStop);
		startStop.setVisible(true);
                
		settings=new Settings();
		settings.setBounds(525,550,100,36);
		add(settings);
		settings.setVisible(true);
                
		settingsdone=new Done();
		settingsdone.setBounds(225,550,100,36);
		add(settingsdone);
		settingsdone.setVisible(false);
		settingsdone.setEnabled(false);
        
		next=new Next();
		next.setBounds(125,550,100,36);
		add(next); 
		next.setVisible(true);

        
      
        
		speed=new Speed();
		speed.setBounds(325,550,100,36);
		add(speed);
		speed.setVisible(true);
                
		clear=new Clear();
		clear.setBounds(325,550,100,36);
		add(clear);
		clear.setVisible(false);
		clear.setEnabled(false);
        
		reset=new Reset();
		reset.setBounds(425,550,100,36);
		add(reset);
		reset.setVisible(true);
		reset.setEnabled(true);
        
		repaint();
                
	}
        

	public void paintComponent(Graphics g)
	{
            
		final int TIME_BETWEEN_REPLOTS = n; // change to your liking
		
		g.setColor(Color.BLACK);
                
		drawGrid(g);	
                
		if (paintloop)
		{
			try 
			{
				Thread.sleep(TIME_BETWEEN_REPLOTS);
			} 
			catch (InterruptedException e) 
			{
				e.printStackTrace();
			}
		//disallows other button discluding faster and slower when game is active
		settings.setEnabled(false);
		next.setEnabled(false);
		reset.setEnabled(false);
				
		lifeSort();		
		repaint();
                        
                        
		}
		else 
		{
			settings.setEnabled(true); 
			next.setEnabled(true); 
			reset.setEnabled(true);
		}
		
		if(poped)//runs the population editor
		{
			paintloop=false;
           
           
			//Calibrate.setVisible(true);
			startStop.setEnabled(false);
           
			speed.setEnabled(false);
			next.setEnabled(false);
			settings.setEnabled(false);
			settings.setVisible(false);
			startStop.setVisible(false);
           
			speed.setVisible(false);
			next.setVisible(false);
           
			settingsdone.setEnabled(true);
			settingsdone.setVisible(true);
			clear.setEnabled(true);
			clear.setVisible(true);
			
			
			repaint();
           
    
           
		}
		for(int i=0;i<100;i++)
		{
			for(int j=0;j<80;j++)
			{
				if(life[i][j]==true)
				{
					g.setColor(Color.BLUE);
					g.fillRect((i*(CELL_WIDTH+1))+(X_GRID_OFFSET+1),(j*(CELL_HEIGHT+1))+(Y_GRID_OFFSET+1),5,5);
				}
			}
		}
		repaint();
		g.setColor(Color.BLACK);
		if(startStop.isSelected()) 
		{
			paintloop=true;
		}
        
		String turn1=Integer.toString(turn);
		g.drawString("Set: "+turn1, 500, 600);
		g.drawString("*Reset sets all shapes to their original form regardless of turn implemented",25,650);
		g.drawString("The Speed Slider has slower to the right and faster to the left",25,670);
        
		repaint();
            
	}
        
 

	public void togglePaintLoop()
	{
		paintloop = !paintloop;
	}


	public void setPaintLoop(boolean value) 
	{
		paintloop = value;
	}
	
	public boolean getPaintLoop()
	{
		return paintloop;
	}


	void drawGrid(Graphics g) 
	{
		for (int row = 0; row <= ROWS; row++) {
			g.drawLine(X_GRID_OFFSET,
					Y_GRID_OFFSET + (row * (CELL_HEIGHT + 1)), X_GRID_OFFSET
					+ COLS * (CELL_WIDTH + 1), Y_GRID_OFFSET
					+ (row * (CELL_HEIGHT + 1)));
		}
		for (int col = 0; col <= COLS; col++) {
			g.drawLine(X_GRID_OFFSET + (col * (CELL_WIDTH + 1)), Y_GRID_OFFSET,
					X_GRID_OFFSET + (col * (CELL_WIDTH + 1)), Y_GRID_OFFSET
					+ ROWS * (CELL_HEIGHT + 1));
		}
		for(int i=25;i<625;i=i+6)
		{
			for(int j=40;j<520;j=j+6)
			{
				g.drawRect(i,j,6,6);
			}
		}
	}
	
	public void lifeSort()
	{
		for(int i=0;i<100;i++)
		{
			for(int j=0;j<80;j++)
			{
				int count=0; //counts the amount of alive neighbors
				int iPlusOne=i+1;
				int jPlusOne=j+1;
				int iMinusOne=i-1;
				int jMinusOne=j-1;
				if(iPlusOne==100)//if at rightmost row: wraps around
				{
					iPlusOne=0;
				}
				if(jPlusOne==80) //if at bottom row
				{
					jPlusOne=0;
				}
				if(iMinusOne<0)//if at top row
				{
					iMinusOne=99;
				}
				if(jMinusOne<0)//if at leftmost row
				{
					jMinusOne=79;
				}
				//names use positions on numpad. position 5 is cell being observed
				boolean neighbor1=life[iMinusOne][jPlusOne];
				boolean neighbor2=life[i][jPlusOne];
				boolean neighbor3=life[iPlusOne][jPlusOne];
				boolean neighbor4=life[iMinusOne][j];
				boolean neighbor6=life[iPlusOne][j];
				boolean neighbor7=life[iMinusOne][jMinusOne];
				boolean neighbor8=life[i][jMinusOne];
				boolean neighbor9=life[iPlusOne][jMinusOne];
				if(neighbor1==true)
				{
					count++;
				}
				if(neighbor2==true)
				{
					count++;
				}
				if(neighbor3==true)
				{
					count++;
				}
				if(neighbor4==true)
				{
					count++;
				}
				if(neighbor6==true)
				{
					count++;
				}
				if(neighbor7==true)
				{
					count++;
				}
				if(neighbor8==true)
				{
					count++;
				}
				if(neighbor9==true)
				{
					count++;
				}
				switch(count) //logic for game
				{
					case 0: temp[i][j]=false; //no neighbors
						break;
					case 1: temp[i][j]=false; //one neighbor
						break;
					//for 2 neighbors see below
					case 3: temp[i][j]=true; //3 neighbors
						break;
					default: temp[i][j]=false; //4 or more neighbors
						break;
				}
				if(count==2 && life[i][j]==true) // 2 neighbors only apply to already live cells; 2 neighbors will not populate a cell
				{
					temp[i][j]=true;
				}
			}
		}
		for(int i=0;i<100;i++)
		{
			for(int j=0;j<80;j++)
			{
				life[i][j]=temp[i][j];
			}
		}
	}	
	public void mouseClicked(MouseEvent arg0) 
	{
		/*System.out.println("MouseX: "+mouseX);
		System.out.println("MouseY: "+mouseY);
		System.out.println("ChangedX: "+changedx);
		System.out.println("ChangedY: "+changedy);*/
		SHAFIQSIDEK_Cell cell = new SHAFIQSIDEK_Cell(arg0.getX()-25,arg0.getY()-40);
		int x=cell.getX();
		int y=cell.getY();
		if(life[x][y]==true)
		{
			life[x][y]=false;
			original[x][y]=false;
			//System.out.println("Cell placed");
		}
		else
		{
			life[x][y]=true;
			original[x][y]=true;
			//System.out.println("Cell placed");
		}
		//System.out.println("X: "+x);
		//System.out.println("Y: "+y);
	}


	public void mouseEntered(MouseEvent arg0) 
	{
		
	}


	public void mouseExited(MouseEvent arg0) 
	{
		
	}


	public void mousePressed(MouseEvent arg0) 
	{
 	}
        


	public void mouseReleased(MouseEvent arg0) 
	{
		//repaint();
	}


	public void mouseDragged(MouseEvent arg0) 
	{
		/*Graphics g=getGraphics();
		g.setColor(Color.YELLOW);
		g.fillRect((int)mouseX,(int)mouseY,6,6);
		paint(g);*/
		//mousePressed(arg0);
		SHAFIQSIDEK_Cell cell = new SHAFIQSIDEK_Cell(arg0.getX()-25,arg0.getY()-40);
		int x=cell.getX();
		int y=cell.getY();
		if(life[x][y]==true)
		{
			life[x][y]=false;
			original[x][y]=false;
			//System.out.println("Cell placed");
		}
		else
		{
			life[x][y]=true;
			original[x][y]=true;
			//System.out.println("Cell placed");
		}
	}


	public void mouseMoved(MouseEvent arg0) 
	{
		mouseX=arg0.getX();
		mouseY=arg0.getY();
		changedx=(int)mouseX-25;
		changedy=(int)mouseY-40;
	}
        
	private class StartButton extends JButton implements ActionListener
	{
		public StartButton() 
		{
			super("Start");
			addActionListener(this);
		}

		public void actionPerformed(ActionEvent arg0) 
		{
			//lifeSort(); // test the start button
			if (this.getText().equals("Start"))
			{
				togglePaintLoop();//changes paintloop 
				setText("Stop");
			}
			else
			{
				togglePaintLoop();//changes paintloop
				setText("Start");
			}
			repaint();
		}
	}
	
	private class Next extends JButton implements ActionListener
	{
		public Next() 
		{
			super("Next ");
			addActionListener(this);
		}

		public void actionPerformed(ActionEvent arg0) 
		{
			lifeSort();
			repaint();
		}
	}
        
	private class Settings extends JButton implements ActionListener 
	{
		public Settings() 
		{
			super("AliveSet");
			addActionListener(this);
		}

		public void actionPerformed(ActionEvent arg0) 
		{
			// nextGeneration(); // test the start button
			poped=true;//sets the settings boolean true
			repaint();
		}
	}
        
	private class Done extends JButton implements ActionListener 
	{
		public Done() 
		{
			super("Done");
			addActionListener(this);
		}

		public void actionPerformed(ActionEvent arg0) //returns to top menu
		{
			// nextGeneration(); // test the start button
			poped=false;
			startStop.setEnabled(true);
           
			speed.setEnabled(true);
			next.setEnabled(true);
			settings.setEnabled(true);
			settings.setVisible(true);
			startStop.setVisible(true);
           
			speed.setVisible(true);
			next.setVisible(true);
           
			settingsdone.setEnabled(false);
			settingsdone.setVisible(false);
			clear.setEnabled(false);
			clear.setVisible(false);
			repaint();
		}
	}
	
	
	
	
	private class Speed extends JSlider implements ChangeListener 
	{
		public Speed() 
		{
			super(0,100);
			addChangeListener((ChangeListener) this);
		}

		public void stateChanged(ChangeEvent e) 
		{
			n=getValue()*2;//slider starts in the middle at 50.
			repaint();
		}
	}
	
	
	private class Clear extends JButton implements ActionListener 
	{
		public Clear() 
		{
			super("Clear");
			addActionListener(this);
		}

		public void actionPerformed(ActionEvent arg0) 
		{
			for(int i=0;i<100;i++)
			{
				for(int j=0;j<80;j++)
				{
					life[i][j]=false;//sets all cells to unpopulated
					original[i][j]=false;
				}
			}
			repaint();
		}
	}
	
	
	private class Reset extends JButton implements ActionListener 
	{
		public Reset() 
		{
			super("*Reset");
			addActionListener(this);
		}

		public void actionPerformed(ActionEvent arg0) 
		{
			Graphics g=getGraphics();
			for(int i=0;i<100;i++)
			{
				for(int j=0;j<80;j++)
				{
					life[i][j]=original[i][j];
				}
			}
			repaint();
		}
	}
          
}